﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using yq.Dictionary;
using yq.IBase;
using Db;
using yq.IBase.Table;

namespace yq.Basis
{
    /// <summary>
    /// 缓存基础对象 ，一般model继承这个对象
    /// 继承关系 DbModelBase=> ModelBase
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class ModelBase<T> : IModelBase where T : ModelBase<T>, new()
    {
        /// <summary>
        /// 语句缓存
        /// </summary>
        private static SQLCache sqlString = new SQLCache();

        /// <summary>
        /// 实体类赋值
        /// </summary>
        /// <param name="info">对象实体</param>
        /// <param name="row">数据行,应为全体字段记录</param>
        protected internal abstract void SetValue(T info, DataRow row);

        /// <summary>
        /// 写入主键值
        /// </summary>
        protected internal abstract void SetKeyValue(dynamic id);

        /// <summary>
        /// 获取主键值
        /// </summary>
        protected internal abstract dynamic GetKeyValue();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="comm"></param>
        /// <param name="info"></param>
        /// <param name="cn"></param>
        protected internal abstract void GetDbParameters(System.Data.Common.DbCommand comm, T info, DbHelper cn);

        /// <summary>
        /// 获取列表IList
        /// </summary>
        /// <param name="rows">数据行组,应为全体字段记录</param>
        /// <returns>返回IList对象列表</returns>
        protected internal IList<T> GetIList(DataTable dt)
        {
            IList<T> lists = new List<T>();
            if (dt == null) return lists;
            foreach (DataRow dr in dt.Rows)
            {
                T info = new T();
                SetValue(info, dr);
                lists.Add(info);
            }

            return lists;
        }

        /// <summary>
        /// 获取列表IList
        /// </summary>
        /// <param name="dt">数据集DataTable,应为全体字段记录</param>
        /// <returns>返回IList对象列表</returns>
        protected internal PageList<T> GetPageList(DataTable dt)
        {
            PageList<T> lists = new PageList<T>();

            if (dt == null) return lists;
            foreach (DataRow dr in dt.Rows)
            {
                T info = new T();
                SetValue(info, dr);
                lists.Add(info);
            }

            return lists;
        }

        /// <summary>
        /// 根据主键获取选择性的SQL语句
        /// </summary>
        /// <param name="aat_id">主键值</param>
        /// <returns></returns>
        protected internal string GetSelectKey(string id)
        {
            string sql = GetSelectSql();
            sql += " Where " + GetTableKey() + " = '" + id + "'";

            return sql;
        }

        /// <summary>
        /// 返回Select所有字段的SQL语句,不带From
        /// </summary>
        /// <returns></returns>
        protected internal string GetSelectColumns()
        {
            if (string.IsNullOrEmpty(sqlString.Select))
            {
                StringBuilder sql = new StringBuilder();
                foreach (var info in TableHelper.GetColumns<T>())
                {
                    if (sql.ToString().Length == 0)
                    {
                        sql.Append(info.Code);
                    }
                    else
                    {
                        sql.Append("," + info.Code);
                    }
                }

                sqlString.Select= "select " + sql.ToString();
            }

            return sqlString.Select;
        }

        /// <summary>
        /// 返回Insert所有字段的SQL语句
        /// </summary>
        /// <returns></returns>
        protected internal string GetInsertColumns()
        {
            if (string.IsNullOrEmpty(sqlString.Insert))
            {
                StringBuilder sql = new StringBuilder();
                StringBuilder sqlInsert = new StringBuilder();
                StringBuilder sqlValues = new StringBuilder();

                foreach (var info in TableHelper.GetColumns<T>())
                {
                    if (sqlInsert.ToString().Length == 0)
                    {
                        sqlInsert.Append(info.Code);
                    }
                    else
                    {
                        sqlInsert.Append("," + info.Code);
                    }

                    if (sqlValues.ToString().Length == 0)
                    {
                        sqlValues.Append("@" + info.Code);
                    }
                    else
                    {
                        sqlValues.Append(",@" + info.Code);
                    }
                }
                sql.Append(" Insert Into " + new T().GetTableName() + "(");
                sql.Append(sqlInsert.ToString());
                sql.Append(") Values(");
                sql.Append(sqlValues.ToString());
                sql.Append(")");

                sqlString.Insert=sql.ToString();
            }

            return sqlString.Insert;
        }

        /// <summary>
        /// 返回Update所有字段的SQL语句
        /// </summary>
        /// <returns></returns>
        protected internal string GetUpdateColumns()
        {
            if (string.IsNullOrEmpty(sqlString.Update))
            {
                StringBuilder sql = new StringBuilder();
                sql.Append(" Update " + new T().GetTableName() + " Set ");

                StringBuilder sqlInsert = new StringBuilder();
                foreach (var info in TableHelper.GetColumns<T>())
                {
                    if (info.Code != GetTableKey())
                    {
                        if (sqlInsert.ToString().Length == 0)
                        {
                            sqlInsert.Append(info.Code + "=@" + info.Code);
                        }
                        else
                        {
                            sqlInsert.Append("," + info.Code + "=@" + info.Code);
                        }
                    }
                }
                sql.Append(sqlInsert.ToString());

                sql.Append(" Where " + GetTableKey() + "=@" + GetTableKey());

                if (TableHelper.GetColumns<T>().Count(obj => obj.Code == "version") != 0)
                {
                    //版本号验证
                    sql.Append(" and Version=@_versionOdl ");
                }

                sqlString.Update= sql.ToString();
            }

            return sqlString.Update;
        }


        /// <summary>
        /// 表名称
        /// </summary>
        /// <returns></returns>
        protected internal string GetTableName()
        {
            if (string.IsNullOrEmpty(sqlString.TableName))
            {
                sqlString.TableName = TableHelper.GetTable<T>().Code;
            }

            return sqlString.TableName;
        }

        /// <summary>
        /// 主键ID
        /// </summary>
        /// <returns></returns>
        protected internal string GetTableKey()
        {
            if (string.IsNullOrEmpty(sqlString.TableKye))
            {
                //第一列必须是主键
                sqlString.TableKye = TableHelper.GetTable<T>().Columns[0].Code;
            }

            return sqlString.TableKye;
        }

        /// <summary>
        /// 返回Select 的Where之前(不带where关键字)的SQL语句
        /// </summary>
        /// <param name="sqlWhere">SQL条件,必须从where开始,可以为空</param>
        /// <returns></returns>
        protected internal string GetSelectSql(string sqlWhere = null)
        {
            StringBuilder sql = new StringBuilder();
            sql.Append(GetSelectColumns());
            sql.Append(" From " + GetTableName() + " ");
            if (string.IsNullOrEmpty(sqlWhere) == false)
            {
                sql.Append(sqlWhere);
            }

            return sql.ToString();
        }

        /// <summary>
        /// 返回Select count(1) 的Where之前(不带where关键字)的SQL语句
        /// </summary>
        /// <param name="sqlWhere">SQL条件,必须从where开始,可以为空</param>
        /// <returns></returns>
        protected internal string GetSelectCountSql(string sqlWhere = null)
        {
            StringBuilder sql = new StringBuilder();
            sql.Append(" select count(1) From " + GetTableName() + " ");
            if (string.IsNullOrEmpty(sqlWhere) == false)
            {
                sql.Append(sqlWhere);
            }

            return sql.ToString();
        }

        /// <summary>
        /// 让model 不需要实例化也能调用
        /// </summary>
        public static T Static
        {
            get
            {
                return new T();
            }
        }

        /// <summary>
        /// 加载数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static T Load(int id, CaCheLocdType type = CaCheLocdType.CaChe)
        {
            return Load(id.ToString(), type);
        }

        /// <summary>
        /// 加载数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isdb"></param>
        /// <returns></returns>
        public static T Load(string id, CaCheLocdType type = CaCheLocdType.CaChe)
        {
            T t = new T();

            if (type == CaCheLocdType.CaChe)
            {
                t = yq.CaChe<T>.Client().HGet(id);
            }


            if (type == CaCheLocdType.CaChe  || t.IsLoad == false)
            {
#warning 访问远程

                Db.DbHelper db = new Db.DbHelper();
                var cm = db.GetSqlStringCommond(new T().GetSelectKey(id));
                DataTable dt = db.ExecuteDataTable(cm);

                if (dt.Rows.Count != 0)
                {
                    new T().SetValue(t, dt.Rows[0]);
                    yq.CaChe<T>.Client().HSet(id, t);
                }
            }

            return t ?? new T();
        }

        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="id"></param>
        public static void Remove(string id)
        {
            yq.CaChe<T>.Client().HRemove(id);
        }

        /// <summary>
        /// 移除
        /// </summary>
        /// <param name="id"></param>
        public static void Remove(int id)
        {
            Remove(id.ToString());
        }

        /// <summary>
        /// 重新加载
        /// </summary>
        /// <param name="id"></param>
        public void LocdModel(string id, CaCheLocdType type = CaCheLocdType.CaChe)
        {
            T t = Load(id, CaCheLocdType.Db);
            SetValue(t);
        }


    }

    /// <summary>
    /// 加载文件类型
    /// </summary>
    public enum CaCheLocdType
    {
        /// <summary>
        /// 数据库
        /// </summary>
        Db,

        /// <summary>
        /// 缓存
        /// </summary>
        CaChe
    }

    /// <summary>
    /// sql语句缓存
    /// </summary>
    public class SQLCache
    {
        public string Insert { get; set; }

        public string Update { get; set; }

        public string Select { get; set; }

        public string TableName { get; set; }

        public string TableKye { get; set; }
    }

}
